home *** CD-ROM | disk | FTP | other *** search
- /*
- 3 Circles - Hit Test
-
- This application creates three circles on top of a black rectangle the size of the portRect of the window. Each circle is
- colored in an RGB color with a the "addMode" transfer mode. The user will be able to select one of the circles and drag
- it around the window. Anytime, one of the circles intersects another, the transfer mode of both circles will be applied
- to the intersection of the two shapes, thereby creating a new color when the shapes are redrawn. I use the QuickDraw
- GX offscreen library to produce flicker free double buffering of the shapes within the window. You will see a little
- flicker when you are running the "debugging" version of the GXGraphics(debug) init. It looks really nice with
- non-debugging init.
-
- Enjoy,
-
- ...Luke
-
- >> Pete "Luke" Alexander
- >> Developer Technical Support
-
- KNOWN BUGS:
- 1) If you drag the window to a monitor which is not in color, some of the circles will disappear. In some cases, this is
- the correct behavior, but in others it is not.
-
- 2) If drag the window to span across two different depth monitors, all of the
-
- NOTES:
- • This file requires the following files to run correctly:
- "graphics shell.c", "ColorLibrary.c", "GraphicsDebugLibrary.c", "OffscreenLibrary.c", "OvalLibrary.c",
- "PictureLibrary.c","QDLibrary.c", "ShapeLibrary.c", "TransferModeLibrary.c", "TransformLibrary.c".
-
- • This file prints the "best" in landscape mode.
-
- ©1990 -1996 Apple Computer, Inc.
- All rights reserved.
-
- Change History:
-
- 4/96 bob Updated the above "NOTES", and copyright date.
- Updated #includes to support changed GX Library names.
-
- */
-
-
-
- #include <Events.h>
- #include <Windows.h>
- #include <Quickdraw.h>
-
- #include <GXGraphics.h>
- #include <GXEnvironment.h>
- #include "GraphicsLibraries.h"
- #include "QDLibrary.h"
- #include "OffscreenLibrary.h"
-
- #include "graphics shell.h"
-
- #define kWinWidth 400 /* The window width. */
- #define kWinHeight 400 /* The window height. */
-
- #define useOffScreen
-
- //
- // Set up the title and size of the window
- //
- Rect gWindowQDRect = {40, 10, kWinWidth, kWinHeight};
- Str255 gWindowTitle = "\pClick and drag a circle...";
-
-
- //
- // gGraphicsHeapSize sets the size of the graphics heap created by calling the NewGraphicsClient routine
- // in main () within graphics shell.c. You can determine the amount of graphics heap required by using GraphicsBug.
- // With gGraphicsHeapSize set to 25k, I had 2 free blocks left in the graphics heap. Sounds good to me.
- //
- long gGraphicsHeapSize = 375;
-
-
- gxShape gThePicture;
- offscreen gAnimationWorld, gAnimationWorldBackGround; /* Off-screen bit map for marquee animation */
- extern gxViewPort gTheWindowsViewPort;
-
-
-
- /*------ DoInitialization ---------------------------------------------------------------------------------
- **
- ** Create the background rectangle and the 3 circles.
- */
- void DoInitialization(theWindow)
- WindowPtr theWindow;
- {
- gxShape myCircle, tempCircleShape;
- gxRectangle circleGeometry = {ff(15), ff(15), ff(115), ff(115)};
- gxShape backBits, baseBits,
- theBackground; // Off-screen bitmap to use as base for off-screen bitmap
- gxBitmap baseMap; // Bitmap to use as base for off-screen drawing environment
- gxPoint mapPos; // Position of the bit map
- gxColor rgbColor;
- Rect windowRect;
- CTabHandle standardClut;
- gxColorSet setOfColors;
- gxTransform savedTransform; // Transform from gAnimationWorldBackGround bit map shape
-
- //
- // Create a picture which will contain the 3 circles and the back background rectangle. We will be adding a
- // unique copy of each circle to our picture - "gThePicture" by calling GXSetPictureParts below.
- //
- gThePicture = GXNewShape( gxPictureType );
-
- //
- // Create the black background rectangle and add it to our picture - "gThePicture". We also set it's hit testing
- // information to prevent it from being moved (i.e. hit tested). Otherwise, the user could move our background.
- //
- SetShapeCommonColor ( gWindowBoundsShape, gxBlack );
- GXSetShapeHitTest( gWindowBoundsShape, gxNoPart, 0 );
- GXSetPictureParts( gThePicture, 0, 0, 1, &gWindowBoundsShape, nil, nil, nil );
-
- //
- // Create the three circles: with an RGB color and addMode transfer mode.
- //
- // We create an RGB color space, and initially set to to red. We will update the color to be different color in RGB space.
- // The hit testing parameter for each circle is set to allow a user to "hit" the shape any time they click within the
- // geometry of the shape. We will move each circle down the left side of the window. After the circles has been created
- // and defined, the circle will be added to our GX picture - "gThePicture".
- //
- rgbColor.space = gxRGBSpace;
- rgbColor.profile = nil;
- rgbColor.element.rgb.red = 0xffff;
- rgbColor.element.rgb.green = 0x0000;
- rgbColor.element.rgb.blue = 0x0000;
-
- //
- // Create a red circle
- //
- myCircle = NewOval( &circleGeometry );
- GXSetShapeColor( myCircle, &rgbColor );
- SetShapeCommonTransfer( myCircle, gxAddMode );
- GXSetShapeHitTest( myCircle, gxGeometryPart, ff(1) );
- GXSetPictureParts( gThePicture, 0, 0, 1, &myCircle, nil, nil, nil );
-
- //
- // Create a green circle
- //
- tempCircleShape = GXCopyToShape ( nil, myCircle );
- GXDisposeShape( myCircle );
-
- rgbColor.element.rgb.red = 0x0000;
- rgbColor.element.rgb.green = 0xffff;
- GXSetShapeColor( tempCircleShape, &rgbColor );
-
- GXMoveShape ( tempCircleShape, 0, ff(115) );
- GXSetPictureParts( gThePicture, 0, 0, 1, &tempCircleShape, nil, nil, nil );
-
- //
- // Create a blue circle
- //
- myCircle = GXCopyToShape ( nil, tempCircleShape );
- GXDisposeShape( tempCircleShape );
-
- rgbColor.element.rgb.green = 0x0000;
- rgbColor.element.rgb.blue = 0xffff;
- GXSetShapeColor( myCircle, &rgbColor );
-
- GXMoveShape ( myCircle, 0, ff(115) );
- SetShapeCommonColor( myCircle, blue );
- GXSetPictureParts( gThePicture, 0, 0, 1, &myCircle, nil, nil, nil );
-
- GXDisposeShape( myCircle );
-
- //
- // Create a color set from the standard color table used by the system. This color set will be used
- // when we create the GX off screen worlds to make sure they contain the appropriate colors possible
- // when drawing to a window.
- //
- standardClut = GetCTable( 72 );
- setOfColors = CTableToColorSet( standardClut );
- DisposCTable( standardClut );
-
- //
- // Set up the bitmap shape which will be used for our GX off-screen worlds...
- //
- windowRect = (*theWindow).portRect;
-
- baseMap.image = nil;
- baseMap.width = windowRect.right - windowRect.left;
- baseMap.height = windowRect.bottom - windowRect.top;
- baseMap.rowBytes = 0;
- baseMap.pixelSize = 8;
- baseMap.space = gxIndexedSpace;
- baseMap.set = setOfColors;
- baseMap.profile = nil;
-
- mapPos.x = mapPos.y = 0;
-
- //
- // Create 2 GX off screen worlds: one for the background contents of the window (named: gAnimationWorldBackGround)
- // and one for the drawing of the circle as the user drags one around the screen.
- //
- baseBits = GXNewBitmap( &baseMap, &mapPos );
- CreateOffscreen( &gAnimationWorld, baseBits );
- GXDisposeShape( baseBits );
-
- baseBits = GXNewBitmap( &baseMap, &mapPos );
- CreateOffscreen( &gAnimationWorldBackGround, baseBits );
- GXDisposeShape( baseBits);
- GXDisposeColorSet( setOfColors );
-
- //
- // Initialize the gAnimationWorldBackGround off screen to white. We accomplish this by creating a shape
- // containing a rectangle, set it's transform to the off screen world, and draw the shape by calling GXDrawShape.
- // The shape draws to the off screen world because the it's transform points to it
- //
- theBackground = GXCopyToShape ( nil, gWindowBoundsShape );
-
- SetShapeCommonColor ( theBackground, gxWhite );
- GXSetShapeTransform( theBackground, gAnimationWorldBackGround.xform );
- GXDrawShape ( theBackground );
- GXDisposeShape( theBackground) ;
-
- //
- // Set the transform of our gAnimationWorld off screen world same as our gAnimationWorldBackGround
- // off screen world.
- //
- savedTransform = GXGetShapeTransform( gAnimationWorldBackGround.draw );
- GXSetShapeTransform( gAnimationWorldBackGround.draw, gAnimationWorld.xform );
- }
-
-
- /*------ DoClick ---------------------------------------------------------------------------------------*/
- void DoClick( orgMouseLoc, theWindow )
- gxPoint orgMouseLoc;
- WindowPtr theWindow;
- {
- gxHitTestInfo test;
- gxShape hit;
-
- GXIgnoreGraphicsNotice (transform_already_set);
-
- if ( GXHitTestPicture( gThePicture, &orgMouseLoc, &test, 1, 1 ) )
- {
- if ( StillDown() )
- {
- gxShape pageShape, tempShape;
- gxPoint newMouseLoc;
- Point currMouseLoc;
-
- //
- // Get the shape hit by the user from the picture.
- //
- hit = GetPictureItem( test.containerPicture, test.containerIndex, nil, nil, nil, nil );
- GXSetShapeTransform( hit, gAnimationWorld.xform );
-
- //
- // Remove the hit shape from the picture and redraw it.
- //
- pageShape = GXCopyToShape ( nil, test.containerPicture );
- tempShape = ExtractShape( pageShape, test.containerIndex, 1 );
- GXDisposeShape ( tempShape );
-
- GXSetShapeTransform( pageShape, gAnimationWorldBackGround.xform );
- GXDrawShape ( pageShape );
-
-
- while ( WaitMouseUp() )
- {
- //
- // Update the mouse location after the user has moved it. How? Get the mouse location from
- // the Quickdraw based toolbox with the GetMouse function. We need to convert the QD point into a
- // fixed gxPoint, referring to the viewPort the mouse is located.
- //
- GetMouse( &currMouseLoc );
- LocalToGlobal( &currMouseLoc );
- GXConvertQDPoint( &currMouseLoc, gTheWindowsViewPort, &newMouseLoc );
-
- //
- // As the user drags a circle, we update the background of the window by drawing the contents
- // of our GX off screen world containing the background of the window by calling
- // GXDrawShape(gAnimationWorldBackGround.draw). We move the circle (i.e. hit) the user is dragging
- // and redraw it. Finally, we update the contents of the window, thereby redrawing the area the
- // user has messed up during the drag and update the location of the mouse.
- //
- if ( (newMouseLoc.x != orgMouseLoc.x) || (newMouseLoc.y != newMouseLoc.y)) // has the mouse moved??
- {
- GXDrawShape( gAnimationWorldBackGround.draw );
-
- GXMoveShape ( hit, newMouseLoc.x - orgMouseLoc.x, newMouseLoc.y - orgMouseLoc.y );
- GXDrawShape( hit );
-
- GXDrawShape( gAnimationWorld.draw );
-
- orgMouseLoc = newMouseLoc;
- }
-
- }
-
- GXDisposeShape ( pageShape );
- }
- }
- GXPopGraphicsNotice ( );
- }
-
-
-
- /*------ DoDraw ---------------------------------------------------------------------------------------*/
-
- void DoDraw( theWindow )
- WindowPtr theWindow;
- {
- GXDrawShape( gThePicture );
- }
-
-
-
- /*------ DoIdle -----------------------------------------------------------------------------------------*/
-
- void DoIdle( theWindow )
- WindowPtr theWindow;
- {
- }
-
-
- /*------ DoDispose -------------------------------------------------------------------------------------*/
-
- void DoDispose( theWindow )
- WindowPtr theWindow;
- {
- DisposeCommonColors ( );
- GXDisposeShape( gThePicture );
- GXDisposeShape( gWindowBoundsShape );
-
- DisposeOffscreen( &gAnimationWorld );
- DisposeOffscreen( &gAnimationWorldBackGround );
-
- DisposeWindow( theWindow );
- }
-
-